package com.hk.web.domain;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author Antinomy
 * @date 17/11/1
 */
public class MerchantSignService {
    private static Logger logger = LoggerFactory.getLogger(MerchantSignService.class);

    private final String HMAC_SHA1_ALGORITHM = "HmacSHA1";

    private final String merchantKey;
    private final String merchantSecret;

    public MerchantSignService(String merchantKey, String merchantSecret) {
        this.merchantKey = merchantKey;
        this.merchantSecret = merchantSecret;
    }

    public String sign(String httpMethod, String path, Map<String, String> params) {
        params.put("merchantKey", merchantKey);

        StringBuilder sb = new StringBuilder();
        Set<String> keySet = new TreeSet<>(params.keySet());
        for (String key : keySet) {
            String value = params.get(key);
            if (value == null) {
                continue;
            }
            sb.append(key);
            sb.append("=");
            sb.append(params.get(key));
            sb.append("&");
        }
        sb.setLength(sb.length() - 1); // trim the last "&"

        String unifiedString = httpMethod.toUpperCase() + ":" + path + ":" + sb.toString();

        logger.info("unified string: " + unifiedString);

        // calc hmac sha1
        try {
            SecretKeySpec secret = new SecretKeySpec(merchantSecret.getBytes(), HMAC_SHA1_ALGORITHM);

            Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
            mac.init(secret);
            byte[] hmac = mac.doFinal(unifiedString.getBytes("UTF-8")); // UTF8

            // base64 encode the hmac
            String sig = Base64.getEncoder().encodeToString(hmac);
            logger.info("signature: " + sig);
            return sig;

        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
